ret = (void *)vstart;
if (ret != NULL) {
- xen_create_contiguous_region(vstart, order);
-
+ /* NB. Hardcode 31 address bits for now: aacraid limitation. */
+ if (xen_create_contiguous_region(vstart, order, 31) != 0) {
+ free_pages(vstart, order);
+ return NULL;
+ }
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
}
swiotlb_init_with_default_size (size_t default_size)
{
unsigned long i, bytes;
+ int rc;
if (!iotlb_nslabs) {
iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
"Use dom0_mem Xen boot parameter to reserve\n"
"some DMA memory (e.g., dom0_mem=-128M).\n");
- xen_create_contiguous_region(
- (unsigned long)iotlb_virt_start, get_order(bytes));
+ /* Hardcode 31 address bits for now: aacraid limitation. */
+ rc = xen_create_contiguous_region(
+ (unsigned long)iotlb_virt_start, get_order(bytes), 31);
+ BUG_ON(rc);
/*
* Allocate and initialize the free list array. This array is used
}
/* Ensure multi-page extents are contiguous in machine memory. */
-void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
+int xen_create_contiguous_region(
+ unsigned long vstart, unsigned int order, unsigned int address_bits)
{
pgd_t *pgd;
pud_t *pud;
/* 2. Get a new contiguous memory extent. */
reservation.extent_order = order;
- reservation.address_bits = 31; /* aacraid limitation */
- BUG_ON(HYPERVISOR_memory_op(
- XENMEM_increase_reservation, &reservation) != 1);
+ reservation.address_bits = address_bits;
+ if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
+ &reservation) != 1)
+ goto fail;
/* 3. Map the new extent in place of old pages. */
for (i = 0; i < (1<<order); i++) {
contiguous_bitmap_set(__pa(vstart) >> PAGE_SHIFT, 1UL << order);
balloon_unlock(flags);
+
+ return 0;
+
+ fail:
+ reservation.extent_order = 0;
+ reservation.address_bits = 0;
+
+ for (i = 0; i < (1<<order); i++) {
+ BUG_ON(HYPERVISOR_memory_op(
+ XENMEM_increase_reservation, &reservation) != 1);
+ BUG_ON(HYPERVISOR_update_va_mapping(
+ vstart + (i*PAGE_SIZE),
+ pfn_pte_ma(mfn, PAGE_KERNEL), 0));
+ xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
+ phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn;
+ }
+
+ flush_tlb_all();
+
+ balloon_unlock(flags);
+
+ return -ENOMEM;
}
void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
unsigned long flags;
#ifdef CONFIG_X86_PAE
- /* this gives us a page below 4GB */
- xen_create_contiguous_region((unsigned long)pgd, 0);
+ /* Ensure pgd resides below 4GB. */
+ int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32);
+ BUG_ON(rc);
#endif
if (!HAVE_SHARED_KERNEL_PMD)
while (skbuff_order_cachep[order] != cachep)
order++;
+ /* Do our best to allocate contiguous memory but fall back to IOMMU. */
if (order != 0)
- xen_create_contiguous_region((unsigned long)buf, order);
+ (void)xen_create_contiguous_region(
+ (unsigned long)buf, order, 0);
scrub_pages(buf, 1 << order);
}
#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
#endif /* linux < 2.6.0 */
-void xen_create_contiguous_region(unsigned long vstart, unsigned int order);
-void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
+/* Returns zero on success else negative errno. */
+int xen_create_contiguous_region(
+ unsigned long vstart, unsigned int order, unsigned int address_bits);
+void xen_destroy_contiguous_region(
+ unsigned long vstart, unsigned int order);
#include <asm/hypercall.h>